home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Experimental BBS Explossion 3
/
Experimental BBS Explossion III.iso
/
comunic
/
twft099b.zip
/
TWTRADE.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1993-06-07
|
60KB
|
1,773 lines
Unit TwTrade;
{
Copyright (C) 1993 by David Myers. All rights reserved. Personal
copying and use of this code permitted. This source cannot be
sold or distributed for more than the cost of media.
}
Interface
Uses
Crt, FlyCom, FParser, TwBuffer, TwScr, TwAnsi, TwLine;
Type
Real3 = Array[1 ..3] of real;
Int3 = ARRAY[1 ..3] of integer;
{ a record to be used perhaps for future expansion }
PortType = RECORD
Name : string;
Loc : string[5];
Class : integer;
Buy,Sell : real3;
END;
Var
DefaultBuy, DefaultSell, DefaultFactor : real;
DeltaFactorOffer, DeltaFactorPsp : real;
{ leave these parameters (buy and sell margins, trading factor)
visible so that external code can alter them }
FUNCTION isdigit( var c : char) : boolean;
Procedure CIMCapture;
Procedure Trade;
Procedure Steal;
Procedure FivePointSteal;
Procedure MultiSteal;
Implementation
Const
StrProd:array[1 .. 3] of string = ('Fuel Ore','Organics','Equipment');
ClassStr:array[0 .. 9] of string = ('','BBS','BSB','SBB','SSB','SBS',
'BSS','SSS','BBB','BBB');
Type
StealType = (STWO,SFIVE,SMULTI);
Procedure Process_Port_Pair(var s1, s2 : string;
var NTrade, Buy1, Buy2,
Haggle1, Haggle2,
P1sells, P2sells : integer);
{
VARIABLES:
INPUT
S1 - 3 character string that defines what Port 1 buys and sells,
such as 'BSB' or 'SSB'.
S2 - 3 character string that defines what Port 2 buys and sells.
OUTPUT
S1 - 3 character string where products that are not traded have
the following letter replacement: 'S' -> 'Y', 'B' -> 'X'.
So if a 'BSB' port is paired with a 'BSS' port, the
output would be 'XYB' and 'XYS' respectively.
S2 - same for Port 2.
NTRADE - Total Number of products that will be traded between
the two ports.
Buy1 - Total number of products that will be bought from Port 1
Buy2 - Total number of products that will be bought from Port 2
Haggle1 - NTrade + any additional number of products that Port 1
attempts to sell.
Haggle2 - NTrade + any additional number of products that Port 2
attempts to sell.
P1sells - total # of products that Port 1 sells.
P2sells - total # of products that Port 2 sells.
}
var
i,x : integer;
BEGIN
Ntrade := 0;
Buy1 := 0;
Buy2 := 0;
Haggle1 := 0;
Haggle2 := 0;
P1sells := 0;
P2sells := 0;
for i := 1 to length(S1) do begin
s1[i] := UpCase(s1[i]);
If s1[i] = 'S' then
Inc(P1sells);
end;
for i := 1 to length(S2) do begin
s2[i] := UpCase(s2[i]);
If s2[i] = 'S' then
Inc(P2sells);
end;
x := Length(S1);
If (Length(S2) < x) then
x := Length(S2);
if x > 3 then
x := 0;
i := 1;
While ( i <= x) do begin
if (s1[i] <> s2[i]) then begin
Inc(NTrade);
Inc(Haggle1);
Inc(Haggle2);
if (s1[i] = 'S') then
Inc(Buy1)
else Inc(Buy2);
end
else begin { s1[i] = s2[i] }
if (s1[i] = 'S') then begin
s1[i] := 'Y';
s2[i] := 'Y';
Inc(Haggle1);
Inc(Haggle2);
end
else begin
s1[i] := 'X';
s2[i] := 'X';
end;
end;
Inc(i);
end;
END;
FUNCTION isdigit( var c : char) : boolean;
{ If the character is a digit, returns TRUE, otherwise returns FALSE }
BEGIN
If ((c >= '0') and (c <= '9')) THEN
isdigit := TRUE
ELSE isdigit := FALSE;
END;
Function str_to_tw_int(s : string) : integer;
{ converts TW integers to Pascal integers }
Var
subtotal,j : integer;
BEGIN
subtotal := 0;
For j := 1 to length(s) do
BEGIN
if isdigit(s[j]) THEN
subtotal := 10*subtotal + ord(s[j]) - ord('0');
END;
str_to_tw_int := subtotal;
END;
FUNCTION pct_to_real(S: string) : real;
{ converts Psychic Probe percentages to real fractions }
Var
j : integer;
subtotal : integer;
t : real;
BEGIN
subtotal := 0;
For j := 1 to length(s)-1 do
BEGIN
if isdigit(s[j]) THEN
subtotal := 10*subtotal + ord(s[j]) - ord('0');
END;
t := subtotal*0.0001;
If ((t < 0.8) or (t > 1.0)) then
t := 1.0;
pct_to_real := t;
END;
FUNCTION pct_in_string(var P : ParseType) : real;
{ finds the percentage in the parsed Psychic Probe string and
converts it to a fraction }
var
j : integer;
t : real;
BEGIN
t := 1.0;
for j := 0 to P.count - 1 do
If isdigit(P.s[j][1]) THEN
t := pct_to_real(P.s[j]);
pct_in_string := t;
END;
FUNCTION Product_Num(s : string) : integer;
var
i, n : integer;
BEGIN
n := 0;
if length(s) > 0 THEN BEGIN
if MatchToken(s,'Fuel') then n := 1;
if MatchToken(s,'Organics') then n := 2;
if MatchToken(s,'Equipment') then n := 3;
END;
Product_Num := n;
END;
Procedure CIMCapture;
{ sets up a capture file that TWASSIST can use }
{ in TWFT 0.95a and up, this routine uses a separate capture
buffer from the open, close, and save commands of the user
buffer. GetALine was modified so that buffer 2 never sees
ANSI commands, so that now you can CIM an ANSI screen and
TWASSIST will never know the difference. }
var
toks : integer;
tradestr, inputstr : string;
Ptrade : ParseType;
Loopit : boolean;
X,Y : Integer;
BEGIN
TradeStr := ' '+#9+#10+#13;
Loopit := TRUE;
If DiskBuff2 and (NOT NotOpen2) then begin
{ if our capture buffer 2 is open, warn user to close and save it first }
SaveScreen(X,Y);
TextColor(Yellow);
TextBackground(Magenta);
GoToXY(10,9); Write(' ');
GoToXY(10,10); Write(' Save Open Buffer 2 First! ');
GoToXY(10,11); Write(' ');
Delay(2000);
NormalVideo;
RestoreScreen;
GotoXY(X,Y);
end
else begin
OpenBuffer2;
Async_Send('V');
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'=Help)?'));
if Loopit then begin
Delay(1000);
Async_Send('G');
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'=Help)?'));
if Loopit then begin
Delay(1000);
Async_Send('K');
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'=Help)?'));
If Loopit then begin { #3 }
Delay(1000);
Async_Send('C');
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'?'));
if Loopit then begin { #4 }
Delay(1000);
Async_Send('X');
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'?'));
If Loopit then begin { #5 }
Delay(1000);
Async_Send_String('╚╔╩╦╠═');
REPEAT
GetALine(toks,tradestr,inputstr,':',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],':'));
If Loopit then begin { #6 }
Delay(1000);
Async_Send('R');
REPEAT
GetALine(toks,tradestr,inputstr,':',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],':'));
If Loopit then begin
Delay(1000);
Async_Send('I');
REPEAT
GetALine(toks,tradestr,inputstr,':',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],':'));
If Loopit then begin
Delay(1000);
Async_Send('Q');
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'?'));
If Loopit then begin
SaveBuffer2;
Delay(1000);
Async_Send('Q');
end; { Loopit #9 }
end; { Loopit #8 }
end; { Loopit #7 }
end; { Loopit #6 }
end; { Loopit #5 }
end; { Loopit #4 }
end; { Loopit #3 }
end; { Loopit #2 }
end; { Loopit #1 }
If (NOT Loopit) then
SaveBuffer2;
end;
END;
Procedure StealAtAPort(var Loop, HasStolen : boolean; Holds : integer;
TypeOfSteal : StealType);
Var
toks,i : integer;
tstr,istr,S : string;
P : parsetype;
temp1, temp2, temp3 : boolean;
X, Y : integer;
BEGIN
Tstr := ' '+#8+#9+#10+#13;
If HasStolen then begin
HasStolen := FALSE;
REPEAT
GetALine(toks,tstr,istr,'?',P,Loop);
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'=Help)?'));
end;
If Loop then begin {#1}
Delay(1000);
X := WhereX; Y := WhereY;
SelectWindow(1);
TextBackground(Cyan);
ClrScr;
Write(' Stealing Equipment. ');
NormalVideo;
SelectWindow(2);
GoToXY(X,Y);
Async_Send('P');
REPEAT
GetALine(toks,tstr,istr,'?',P,Loop);
temp1 := MatchToken(P.s[toks-1],'?');
UNTIL ((NOT Loop) or temp1);
If Loop then begin {#2}
Delay(1000);
Async_Send('R');
REPEAT
GetALine(toks,tstr,istr,']',P,Loop);
temp1 := MatchToken(P.s[toks-1],'[Pause]');
UNTIL ((NOT Loop) or temp1);
If Loop then begin {#3}
Delay(1000);
Async_Send(#13);
REPEAT
GetALine(toks,tstr,istr,')',P,Loop);
temp1 := MatchToken(P.s[toks-1],'(?=Help)');
UNTIL ((NOT Loop) or temp1);
If Loop then begin {#4}
Delay(1000);
Async_Send('S');
REPEAT
GetALine(toks,tstr,istr,'?',P,Loop);
temp1 := MatchToken(P.s[toks-1],'?');
UNTIL ((NOT Loop) or temp1);
If Loop then begin {#5}
Delay(1000);
Async_Send('3');
REPEAT
GetALine(toks,tstr,istr,'?',P,Loop);
temp1 := MatchToken(P.s[toks-1],'swipe?');
UNTIL ((NOT Loop) or temp1);
If Loop then begin {#6}
Str(Holds,S);
S := S + #13;
Delay(1000);
Async_Send_String(S);
REPEAT
UNTIL Async_tx_empty;
REPEAT
GetALine(toks,tstr,istr,'!.',P,Loop);
X := WhereX; Y := WhereY;
SelectWindow(1);
TextBackground(Cyan);
ClrScr;
Write(' Steal Successful? ');
NormalVideo;
SelectWindow(2);
GoToXY(X,Y);
temp1 := MatchToken(P.s[toks-1],'Busted!');
temp2 := MatchToken(P.s[toks-1],'Success!');
temp3 := MatchToken(P.s[toks-1],'point(s).');
UNTIL ((NOT Loop) or temp1 or temp2 or temp3);
If Loop then begin {#7}
If temp1 then begin
Loop := FALSE;
Alarm;
end;
if temp2 or temp3 then begin
REPEAT
GetALine(toks,tstr,istr,'?',P,Loop);
temp1 := MatchToken(P.s[toks-1],'=Help)?');
X := WhereX; Y := WhereY;
SelectWindow(1);
TextBackground(Cyan);
ClrScr;
Write(' End of Steal? ');
NormalVideo;
SelectWindow(2);
GoToXY(X,Y);
UNTIL ((NOT Loop) or temp1);
end;
end; { if Loop #7 }
end; { if Loop #6 }
end; { if Loop #5 }
end; { if Loop #4 }
end; { if Loop #3}
end; { if Loop #2}
if Loop then begin
{ ------------------- }
X := WhereX; Y := WhereY;
TextColor(White);
TextBackground(Cyan);
SelectWindow(1);
ClrScr;
If (TypeOfSteal = SMulti) then
Write(' === ALT 6 - MultiSteal Steal/Sell. ALT Q Quits. === ');
If (TypeOfSteal = SFive) then
Write(' === ALT 5- 5 Point Steal/Sell. ALT Q Quits. === ');
If (TypeOfSteal = STwo) then
Write(' === ALT S- Tradewars Steal/Sell. ALT Q Quits. === ');
NormalVideo;
SelectWindow(2);
GoToXY(X,Y);
end; { if loop for exit code.}
end; { if Loop #1}
END;
{ an experimental 5 point algo, gutting the older trade algo }
Procedure FivePointTrade( PortBuy : string;
Port4Sale : integer;
var BP5P, FO5P : integer;
Hold : Int3;
MaxCount : integer;
var Loopit : boolean);
{
experimental 5 point trading algo..
VARIABLES:
INPUT:
PortBuy - processed 3 character string of the 'XYS' variety.
Port4Sale - The number of products the port has for sale.
BP5P - 5 point best price.
FO5P - port offer used to determine best price.
Hold - array of number of Holds of Fuel Ore, Org., and Eq. traded.
MaxCount - # of Haggles required for this port
Loopit - TRUE
OUTPUT:
Loopit - FALSE if ALT-Q pressed.
LOCAL:
TradeStr, InputStr, Ptrade, toks : GetALine vars.
HasSold - Boolean used to flag whether port has bought product.
PCount - # of Haggles so far.
PBuyCount - # of items for sale so far.
CurrentProduct - current product being traded.
OldOffer - the previous port offer
PortOffer - the current port offer
OurOffer - our current offer.
OldBid - our first offer.
Delta - positive difference between PortOffer and OldOffer.
Done - FALSE while macro and port haggling over price of product.
ProbePct - fraction of best price returned by Psychic Probe
}
Var
TradeStr, InputStr, S : string;
toks : integer;
PTrade : ParseType;
HasSold : boolean;
PCount, PBuyCount : integer;
CurrentProduct : integer;
OldOffer,PortOffer,OurOffer : integer;
OldBid : integer;
Done : boolean;
temp1, temp2, tempb1, tempb2, tempb3, tempb4, tempb5 : boolean;
Delta : integer;
DeltaH : real;
ProbePct : real;
X,Y : integer;
BEGIN
Tradestr := ' '+#9+#10+#13;
Delay(1000);
Async_Send('P');
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'?'));
Delay(500);
Async_Send('T');
HasSold := FALSE;
PCount := 0;
PBuyCount := 0;
REPEAT { Have You exhausted this port? }
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-2],'sell') or
MatchToken(Ptrade.s[toks-2],'buy'));
If ((NOT HasSold) and MatchToken(Ptrade.s[toks-2],'buy') and
(Port4Sale < MaxCount)) THEN
MaxCount := Port4Sale; { take care of empty holds situation }
If (MatchToken(Ptrade.s[toks-2],'buy') and Loopit) THEN BEGIN
Currentproduct := Product_Num(Ptrade.s[4]);
S := '0'+#13;
Async_Send_String(S);
Inc(PCount);
Inc(PBuyCount);
END; { If 'buy' }
If (MatchToken(Ptrade.s[toks-2],'sell') and Loopit) THEN BEGIN
Currentproduct := Product_Num(Ptrade.s[4]);
IF (Currentproduct <> 3) THEN BEGIN
S := '0'+#13;
Async_Send_String(S);
END
ELSE BEGIN
S := '';
S := #13;
Async_Send_String(S);
OldOffer := 0;
Done := FALSE;
{ add a loop here }
While ((NOT Done) and Loopit) do BEGIN
If (OldOffer < 1) Then BEGIN
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
temp1 := MatchToken(Ptrade.s[toks-1],'many.');
temp2 := MatchToken(Ptrade.s[toks-1],'credits.');
UNTIL ((NOT Loopit) or temp1 or temp2);
END;
if temp1 then begin
Loopit := FALSE;
Alarm;
end;
If (Loopit) then BEGIN {internal Loopit #1}
PortOffer := str_to_tw_int(Ptrade.s[4]);
If (BP5P < 1) then begin
FO5P := PortOffer;
OurOffer := PortOffer;
DeltaH := 0.0;
end
else begin
If (OldOffer < 1) then begin
Delta := PortOffer - FO5P;
DeltaH := Delta/Hold[3];
Delta := Hold[3]*round(DeltaH);
OurOffer := BP5P + round(Delta);
{ ship out price }
X := WhereX; Y := WhereY;
SelectWindow(1);
TextBackground(Green);
ClrScr;
Write(' Delta Holds = ',DeltaH:5:2,' Best price = ',OurOffer);
NormalVideo;
SelectWindow(2);
GoToXY(X,Y);
end
else begin
Delta := PortOffer - OldOffer;
DeltaH := Delta/(Hold[3]*0.3);
BP5P := BP5P + round(0.3*Delta);
OurOffer := OldBid - trunc(2.333333333*Delta);
If (Delta < 1) then begin
Dec(OurOffer);
OurOffer := 5*(OurOffer div 5);
{ we've missed the boat so maybe we start again }
end;
end; { oldoffer }
END; { else BP5P < 1 }
{ okay, Port asking for offer }
If Loopit then BEGIN
Str(OurOffer,S);
S := S + #13;
Delay(500);
Async_Send_String(S);
{ gak, hard part here }
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
tempb1 := MatchToken(Ptrade.s[toks-1],'credits.');
tempb2 := MatchToken(Ptrade.s[0],'<P-Probe');
tempb3 := MatchToken(Ptrade.s[toks-2],'experience');
tempb4 := MatchToken(Ptrade.s[3],'credits');
tempb5 := MatchToken(Ptrade.s[toks-1],'interested.');
UNTIL ((NOT Loopit) or tempb1 or tempb2 or
tempb3 or tempb4 or tempb5);
If tempb5 then begin
Loopit := FALSE;
Alarm;
end;
If tempb1 then BEGIN
Done := FALSE;
OldBid := OurOffer;
OldOffer := PortOffer;
END
else Done := TRUE;
If (Done and Loopit) then begin
HasSold := TRUE;
Inc(PCount);
if tempb2 then begin
ProbePct := pct_in_string(Ptrade);
BP5P := round(OurOffer/ProbePct);
FO5P := PortOffer;
END;
if tempb3 and (BP5P < 1) then begin
BP5P := round(OurOffer/0.99);
FO5P := PortOffer;
END;
if tempb4 and (BP5P < 1) then begin
BP5P := round(OurOffer/0.97);
FO5P := PortOffer;
END;
end; { Done }
END; { internal Loopit #2}
END; {internal Loopit #1}
END; {While NOT Done}
END; { else begin }
END; { If 'sell' }
UNTIL ((PCount >= MaxCount) or (NOT Loopit)); {port loop}
END;
Procedure TradeAtAPort( PortBuy : string;
Port4Sale : integer;
var Buy,Sell : Real3;
var Factor: Real3;
Hold : Int3;
MaxCount : integer;
var Loopit : boolean);
{ conducts a single trading round with a single port. Uses portbuy
to determine how many products will be bought. Can handle a case
where the ship has no products or when the ship has all the products
that are to be traded with this port. Uses a second order correction
theory to alter both the buy and sell margins as well as the factor
used to alter bids in order to optimize both the first bid as well
as the rate at which agreement is reached when barter is involved.
VARIABLES:
INPUT:
PortBuy - processed 3 character string of the 'XYS' variety.
Port4Sale - The number of products the port has for sale.
Buy - array of fractions to reduce port offer by.
Sell - array of fractions to increase port offer by.
Factor - array of linear factors to multiply differences by.
Hold - array of number of Holds of Fuel Ore, Org., and Eq. traded.
MaxCount - # of Haggles required for this port
Loopit - TRUE
OUTPUT:
Loopit - FALSE if ALT-Q pressed.
LOCAL:
TradeStr, InputStr, Ptrade, toks : GetALine vars.
HasSold - Boolean used to flag whether port has bought product.
PCount - # of Haggles so far.
PBuyCount - # of items for sale so far.
CurrentProduct - current product being traded.
OrigOffer - the first port offer
OldOffer - the previous port offer
PortOffer - the current port offer
PortOffer2 - a double check on the port offer.
OurOffer - our current offer.
OldBid - our first offer.
FirstOffer - A Boolean that flags whether this is the first price the
port offers.
SecondOffer - A Boolean that flags whether this is the second price the
port offers.
f - a function defined by the equation:
BEST PRICE ESTIMATE - BEST PRICE = f*abs(PortOffer - OldOffer)
In a linear difference model then Factor is related to f
by the equation f = 1/(Factor + 1), and Factor = 1/f - 1.
We use f to calculate second order Buy/Sell and Factor corrections.
diff1, diff2 - positive differences between the first pair of
port offers and the second pair of port offers.
We use the ratio of diff2 over diff1 to determine
real-time changes in f from our assumed original
value of 0.3
Delta - positive difference between PortOffer and OldOffer.
Done - FALSE while macro and port haggling over price of product.
ProbePct - fraction of best price returned by Psychic Probe
temp1 - true when port has insufficient product to sell.
tempb1, tempb2, tempb3, tempb4 - used to alter prices..
If tempb1 is true, the port has offered a new price and we
have to continue to barter. The program then alters the
margins and bartering factors according to second order
overbidding theory.
If tempb2 is true, then price has been decided and the Psychic
probe has returned a percent. If this was the first offer, we adjust
our buy and sell margins accoringly.
If tempb3 is true, then price has been decided and there was no
Psychic Probe used. If we get just 1 experience and this was the
first offer, adjust buy and sell margins by 1%.
If tempb4 is true, then price has been decided and there was no
Psychic Probe input. Furthermore, our bid was so low that no
experience was earned, and our price is less than 98% of best.
We therefore adjust buy/sell margins by 3% if this was first bid.
tempb5 - TRUE if buy/sell loop terminates because port is not interested.
}
Label
StartOver, StartOver2;
Var
TradeStr, InputStr, S : string;
toks : integer;
PTrade : ParseType;
HasSold : boolean;
PCount, PBuyCount : integer;
CurrentProduct : integer;
OrigOffer,OldOffer,PortOffer,PortOffer2,OurOffer : integer;
OldBid : integer;
diff1, diff2 : integer;
FirstOffer,SecondOffer,Done : boolean;
temp1, temp2, tempb1, tempb2, tempb3, tempb4, tempb5 : boolean;
Delta : integer;
ProbePct,f,OldFactor : real;
XCol, XBak : integer;
X,Y : integer;
BEGIN
Tradestr := ' '+#9+#10+#13;
Delay(1000);
Async_Send('P');
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'?'));
Delay(500);
Async_Send('T');
HasSold := FALSE;
PCount := 0;
PBuyCount := 0;
REPEAT { Have You exhausted this port? }
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-2],'sell') or
MatchToken(Ptrade.s[toks-2],'buy'));
If ((NOT HasSold) and MatchToken(Ptrade.s[toks-2],'buy') and
(Port4Sale < MaxCount)) THEN
MaxCount := Port4Sale; { take care of empty holds situation }
If (MatchToken(Ptrade.s[toks-2],'buy') and Loopit) THEN BEGIN
Currentproduct := Product_Num(Ptrade.s[4]);
IF (PortBuy[Currentproduct] <> 'S') THEN BEGIN
S := '0'+#13;
Async_Send_String(S);
Inc(PCount);
Inc(PBuyCount);
END
ELSE BEGIN
Str(Hold[CurrentProduct],S);
S := S + #13;
Async_Send_String(S);
OldOffer := 0;
FirstOffer := TRUE;
SecondOffer := FALSE;
Done := FALSE;
X := WhereX; Y := WhereY;
SelectWindow(1);
XCol := TextAttr and 15;
XBak := (TextAttr shr 4) and 7;
TextColor(Blue);
TextBackground(LightCyan);
ClrScr;
Write(' Buy[',StrProd[CurrentProduct],'] = ',Buy[CurrentProduct]:6:3,
' ■■ Factor[',StrProd[CurrentProduct],'] = ',
Factor[CurrentProduct]:7:4);
TextColor(XCol);
TextBackground(XBak);
SelectWindow(2);
GoToXY(X,Y);
{ add a loop here }
While ((NOT Done) and Loopit) do BEGIN
If FirstOffer Then BEGIN
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
temp1 := MatchToken(Ptrade.s[toks-1],'many.');
temp2 := MatchToken(Ptrade.s[toks-1],'credits.');
UNTIL ((NOT Loopit) or temp1 or temp2);
END;
if temp1 then begin
Loopit := FALSE;
Alarm;
end;
If (Loopit) then BEGIN {internal Loopit #1}
PortOffer2 := 0;
PortOffer := str_to_tw_int(Ptrade.s[4]);
StartOver:
If (OldOffer > 0) THEN BEGIN
Delta := Abs(PortOffer - OldOffer);
OurOffer := OurOffer + round(Factor[CurrentProduct]*Delta);
If (Delta < 1) then
Inc(OurOffer);
If MatchToken(Ptrade.s[1],'final') THEN
Inc(OurOffer);
OldOffer := PortOffer;
END
ELSE BEGIN
OldOffer := PortOffer;
OurOffer := round(PortOffer*Buy[CurrentProduct]);
END;
If (PortOffer2 < 1) then begin
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'?'));
PortOffer2 := str_to_tw_int(Ptrade.s[toks-2]);
{ double check that price }
If (PortOffer2 > 2*PortOffer) then begin
PortOffer := PortOffer2;
goto StartOver;
end;
end;
{ okay, Port asking for offer }
If (Loopit) then BEGIN
Str(OurOffer,S);
S := S + #13;
Async_Send_String(S);
Delay(1000);
{ gak, hard part here }
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
tempb1 := MatchToken(Ptrade.s[toks-1],'credits.');
tempb2 := MatchToken(Ptrade.s[0],'<P-Probe');
tempb3 := MatchToken(Ptrade.s[toks-2],'experience');
tempb4 := MatchToken(Ptrade.s[3],'credits');
tempb5 := MatchToken(Ptrade.s[toks-1],'interested.');
UNTIL ((NOT Loopit) or tempb1 or tempb2 or
tempb3 or tempb4 or tempb5);
If tempb5 then begin
Loopit := FALSE;
Alarm;
end;
If tempb1 then BEGIN
Done := FALSE;
PortOffer := str_to_tw_int(Ptrade.s[4]);
if SecondOffer = TRUE then begin
SecondOffer := FALSE;
{ second order margin and factor corrections}
diff1 := abs(OldOffer - OrigOffer);
diff2 := abs(PortOffer - OldOffer);
if (diff1 >= DeltaFactorOffer) then begin
f := 1.0/(Factor[CurrentProduct] + 1.0);
f := f - diff2/diff1;
Factor[CurrentProduct] := 1.0/f - 1.0;
Buy[CurrentProduct] := (OldBid + diff1/f)/
(OrigOffer);
end;
end;
if FirstOffer = TRUE then begin
FirstOffer := FALSE;
SecondOffer := TRUE;
OrigOffer := OldOffer;
OldBid := OurOffer;
{ make a first order margin correction }
diff1 := abs(PortOffer - OldOffer);
f := 1.0/(Factor[CurrentProduct] + 1.0);
Buy[CurrentProduct] := (OldBid + diff1/f)/
(OrigOffer);
end;
FirstOffer := FALSE;
END
else Done := TRUE;
If (Done and Loopit) then begin
Inc(PCount);
Inc(PBuyCount);
if tempb2 and FirstOffer then begin
ProbePct := pct_in_string(Ptrade);
Buy[CurrentProduct] := Buy[CurrentProduct]*ProbePct;
END; { if tempb2}
if tempb2 and SecondOffer then begin
ProbePct := pct_in_string(Ptrade);
diff2 := abs(OldOffer - OrigOffer);
OldFactor := Factor[CurrentProduct];
if (diff2 > DeltaFactorPsp) then begin
Factor[CurrentProduct] := abs(OurOffer*ProbePct - OldBid)/diff2;
end;
END; { if tempb2}
if tempb3 and FirstOffer then begin
If MatchToken(Ptrade.s[toks-3],'1') then
Buy[CurrentProduct] := Buy[CurrentProduct] - 0.01;
END;
if tempb3 and SecondOffer then begin
diff2 := abs(OldOffer - OrigOffer);
if (diff2 > DeltaFactorPsp) then
Factor[CurrentProduct] := abs(OurOffer*0.99 - OldBid)/diff2;
END; { if tempb2}
if tempb4 and FirstOffer then begin
Buy[CurrentProduct] := Buy[CurrentProduct] - 0.03;
END;
if tempb4 and SecondOffer then begin
diff2 := abs(OldOffer - OrigOffer);
if (diff2 > DeltaFactorPsp) then
Factor[CurrentProduct] := abs(OurOffer*0.98 - OldBid)/diff2;
END; { if tempb2}
end; { Done }
END; { internal Loopit #2}
END; {internal Loopit #1}
END; {While NOT Done}
END; {else if PortBuy.. }
END; { If 'buy' }
If (MatchToken(Ptrade.s[toks-2],'sell') and Loopit) THEN BEGIN
Currentproduct := Product_Num(Ptrade.s[4]);
IF (PortBuy[Currentproduct] <> 'B') THEN BEGIN
{ lack of this 5 line piece of code in versions 0.92 and below
caused problems with trades between classes 2, 4 and 6}
S := '0'+#13;
Async_Send_String(S);
{ Inc(PCount); Removing this to allow 0 porting with or
without product "onboard". This should help when someone
is trading with megaholds and needs an organic or fuel ore
to lock the holds in. }
END
ELSE BEGIN
S := '';
S := #13;
Async_Send_String(S);
OldOffer := 0;
FirstOffer := TRUE;
SecondOffer := FALSE;
Done := FALSE;
X := WhereX; Y := WhereY;
SelectWindow(1);
XCol := TextAttr and 15;
XBak := (TextAttr shr 4) and 7;
TextColor(White);
TextBackground(Green);
ClrScr;
Write(' Sell[',StrProd[CurrentProduct],'] = ',Sell[CurrentProduct]:6:3,
' ■■ Factor[',StrProd[CurrentProduct],'] = ',Factor[CurrentProduct]:7:4);
TextColor(XCol);
TextBackground(XBak);
SelectWindow(2);
GoToXY(X,Y);
TextColor(XCol);
{ add a loop here }
While ((NOT Done) and Loopit) do BEGIN
If FirstOffer Then BEGIN
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'credits.'));
END;
If (Loopit) then BEGIN {internal Loopit #1}
PortOffer2 := 0;
PortOffer := str_to_tw_int(Ptrade.s[4]);
StartOver2:
If (OldOffer > 0) THEN BEGIN
Delta := Abs(PortOffer - OldOffer);
OurOffer := OurOffer - round(Factor[CurrentProduct]*Delta);
If (Delta < 1) then
Dec(OurOffer);
If MatchToken(Ptrade.s[1],'final') then
Dec(OurOffer);
OldOffer := PortOffer;
END
ELSE BEGIN
OldOffer := PortOffer;
OurOffer := round(PortOffer*Sell[CurrentProduct]);
END;
If (PortOffer2 < 1) then begin
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
UNTIL ((NOT Loopit) or MatchToken(Ptrade.s[toks-1],'?'));
PortOffer2 := str_to_tw_int(Ptrade.s[toks-2]);
{ double check that price }
If (PortOffer2 > 2*PortOffer) then begin
PortOffer := PortOffer2;
goto StartOver2;
end;
end;
{ okay, Port asking for offer }
If Loopit then BEGIN
Str(OurOffer,S);
S := S + #13;
Async_Send_String(S);
Delay(1000);
{ gak, hard part here }
REPEAT
GetALine(toks,tradestr,inputstr,'?',Ptrade,Loopit);
tempb1 := MatchToken(Ptrade.s[toks-1],'credits.');
tempb2 := MatchToken(Ptrade.s[0],'<P-Probe');
tempb3 := MatchToken(Ptrade.s[toks-2],'experience');
tempb4 := MatchToken(Ptrade.s[3],'credits');
tempb5 := MatchToken(Ptrade.s[toks-1],'interested.');
UNTIL ((NOT Loopit) or tempb1 or tempb2 or
tempb3 or tempb4 or tempb5);
If tempb5 then begin
Loopit := FALSE;
Alarm;
end;
If tempb1 then BEGIN
Done := FALSE;
PortOffer := str_to_tw_int(Ptrade.s[4]);
if SecondOffer = TRUE then begin
{ Second order correction assuming Linear
Difference model of port trading }
SecondOffer := FALSE;
diff1 := abs(OldOffer - OrigOffer);
diff2 := abs(PortOffer - OldOffer);
If (diff1 > DeltaFactorOffer) then begin
f := 1.0/(Factor[CurrentProduct] + 1.0);
f := f - diff2/diff1;
Factor[CurrentProduct] := 1.0/f - 1.0;
Sell[CurrentProduct] := (OldBid - diff1/f)/
(OrigOffer);
end;
end;
if FirstOffer = TRUE then begin
FirstOffer := FALSE;
SecondOffer := TRUE;
OrigOffer := OldOffer;
OldBid := OurOffer;
{ make a first order margin correction }
diff1 := abs(PortOffer - OldOffer);
f := 1.0/(Factor[CurrentProduct] + 1.0);
Sell[CurrentProduct] := (OldBid - diff1/f)/
(OrigOffer);
end;
END
else Done := TRUE;
If (Done and Loopit) then begin
HasSold := TRUE;
Inc(PCount);
if tempb2 and FirstOffer then begin
ProbePct := pct_in_string(Ptrade);
Sell[CurrentProduct] := Sell[CurrentProduct]/ProbePct;
END;
if tempb2 and SecondOffer then begin
ProbePct := pct_in_string(Ptrade);
diff2 := abs(OldOffer - OrigOffer);
OldFactor := Factor[CurrentProduct];
if (diff2 > DeltaFactorPsp) then begin
Factor[CurrentProduct] := (OldBid - OurOffer/ProbePct)/diff2;
end;
END; { if tempb2}
if tempb3 and FirstOffer then begin
If MatchToken(Ptrade.s[toks-3],'1') then
Sell[CurrentProduct] := Sell[CurrentProduct] + 0.01;
END;
if tempb3 and SecondOffer then begin
diff2 := abs(OldOffer - OrigOffer);
if (diff2 > DeltaFactorPsp) then
Factor[CurrentProduct] := (OldBid - OurOffer/0.99)/diff2;
END; { if tempb3}
if tempb4 and FirstOffer then begin
Sell[CurrentProduct] := Sell[CurrentProduct] + 0.03;
END;
if tempb4 and SecondOffer then begin
diff2 := abs(OldOffer - OrigOffer);
if (diff2 > DeltaFactorPsp) then
Factor[CurrentProduct] := (OldBid - OurOffer/0.98)/diff2;
END; { if tempb4}
end; { Done }
END; { internal Loopit #2}
END; {internal Loopit #1}
END; {While NOT Done}
END; { else begin }
END; { If 'sell' }
UNTIL ((PCount >= MaxCount) or (NOT Loopit)); {port loop}
END;
Procedure MoveToANewPort(var Port : string; var Loop : boolean);
{ this algorithm is sometimes buggy
4-24-93 - killed bug. Loop was neither passed nor initialized.}
Var
toks,i : integer;
tstr,istr,S : string;
P : parsetype;
temp1, temp2 : boolean;
X, Y : integer;
BEGIN
{ clear out remnants of last trade }
Loop := TRUE;
Tstr := ' '+#9+#10+#13;
X := WhereX; Y := WhereY;
TextColor(White);
TextBackground(Cyan);
SelectWindow(1);
ClrScr;
Write(' === ALT T- Tradewars Paired Port Trading. ALT Q Quits. === ');
NormalVideo;
SelectWindow(2);
GoToXY(X,Y);
REPEAT
GetALine(toks,tstr,istr,'?',P,Loop);
temp1 := MatchToken(P.s[toks-2],'buy');
If temp1 then begin
{ if Equipment zeroed then it is possible for trade loop to terminate
prematurely, so we clear out those trades here }
S := '0'+#13;
Async_Send_String(S);
end;
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'=Help)?'));
Delay(1000); { keep this delay *AFTER* the REPEAT loop! }
If Loop then begin
If (length(Port) < 3) or ((length(Port) = 3) and (Port[1] = '1')) THEN
{ In TW beta 2.0, I wonder how these port numbers will be handled? }
S := Port+#13
ELSE S := Port;
Async_Send_String(S);
REPEAT
GetALine(toks,tstr,istr,'?',P,Loop);
temp2 := MatchToken(P.s[toks-1],'=Help)?');
UNTIL ((NOT Loop) or temp2);
end;
END;
Procedure Trade;
Label
NoTrade;
Var
Port1, Port2, Port1Buy, Port2Buy, tokstr : String;
P1b, P1s : real3;
P2b, P2s : real3;
P1F, P2F : Real3;
NTraded, MaxNBought : integer;
P1_4Sale,P2_4Sale : integer;
P1Haggle, P2Haggle : Integer;
P1Buy, P2Buy : integer;
TotHolds,SumHolds : integer;
Holds : Int3;
Loop : Boolean;
X,Y,i,toks : integer;
P : parsetype;
BEGIN
tokstr := ' ,:;'+#8+#9+#10+#13;
SaveScreen(X,Y);
Window(5,5,40,15);
YellowVideo;
ClrScr;
Loop := TRUE;
for i := 1 to 3 do begin
P1F[i] := DefaultFactor;
P2F[i] := DefaultFactor;
P1B[i] := DefaultBuy;
P1S[i] := DefaultSell;
P2B[i] := DefaultBuy;
P2S[i] := DefaultSell;
end;
Write(' Port 1: ');
ReadLn(Port1);
{ tokenize the string and take the first token to kill any leading
blanks or tabs }
toks := Parse_Str(tokstr,Port1,P);
If toks > 0 then
Port1 := P.s[0];
Write(' Port 1 Type: ');
ReadLn(Port1Buy);
toks := Parse_Str(tokstr,Port1Buy,P);
If toks > 0 then
Port1Buy := P.s[0];
{ if somebody enters a port class, convert it to the 3 char string }
If ((length(Port1Buy) = 1) and (isdigit(Port1Buy[1]))) then
Port1Buy := ClassStr[Ord(Port1Buy[1]) - Ord('0')];
Write(' Port 2: ');
ReadLn(Port2);
toks := Parse_Str(tokstr,Port2,P);
If toks > 0 then
Port2 := P.s[0];
Write(' Port 2 Type: ');
ReadLn(Port2Buy);
toks := Parse_Str(tokstr,Port2Buy,P);
If toks > 0 then
Port2Buy := P.s[0];
{ if somebody enters a port class, convert it to the 3 char string }
If ((length(Port2Buy) = 1) and (isdigit(Port2Buy[1]))) then
Port2Buy := ClassStr[Ord(Port2Buy[1]) - Ord('0')];
{ Find out how many products we can trade and other tedious goodies }
Process_Port_Pair(Port1Buy,Port2Buy,NTraded,P1Buy,P2Buy,
P1Haggle,P2Haggle,P1_4Sale,P2_4Sale);
{ if we have products to trade, then trade }
If (NTraded > 0) THEN
BEGIN
WriteLn(' Num. Products Traded = ',NTraded);
Write(' How many Holds to Trade with : ');
ReadLn(TotHolds);
For i := 1 to 3 do begin
Holds[i] := -1;
If (Port1Buy[i] <> 'X') and (Port1Buy[i] <> 'Y') then begin
Write(' How Many Holds For ',StrProd[i],': ');
ReadLn(Holds[i]);
{ check for zero valued holds. If Holds = 0, then
user must not want to trade the product }
If (Holds[i] = 0) then begin
If Port1Buy[i] = 'S' then begin
Port1Buy[i] := 'Y';
Dec(P1Buy);
{ don't give product any holds if we aren't trading it }
end;
If Port1Buy[i] = 'B' then begin
Port1Buy[i] := 'X';
Dec(P1Haggle);
{ Can't Haggle for it if it isn't onboard }
end;
If Port2Buy[i] = 'S' then begin
Port2Buy[i] := 'Y';
Dec(P2Buy);
{ don't give product any holds if we aren't trading it }
end;
If Port2Buy[i] = 'B' then begin
Port2Buy[i] := 'X';
Dec(P2Haggle);
{ Can't haggle for it if it isn't onboard }
end;
end;
end;
end;
{ trap any weirdness before we divide by P1Buy or P2Buy }
If (P1Buy < 1) then
P1Buy := 1;
If (P2Buy < 1) then
P2Buy := 1;
{
idiot proof input. Set it up so that entering a number of
holds = -1 equally divides holds between products. Note
algorithm works best when holds evenly divisible by 6.
TWFT 0.94 and up:
Note algorithm has been reworked so that any mixture of
-1s, 0s, and positive hold numbers can be mixed. If the
sum of the number of holds is less than the number of
total holds you enter, we assume the user knows what
he is doing and do nothing. If the number is greater
than the total number of holds, we recalculate so that
the trade can be completed.
}
SumHolds := 0;
for i := 1 to 3 do
If (Port1Buy[i] = 'S') then begin
if (Holds[i] < 0) then
Holds[i] := TotHolds div P1Buy;
SumHolds := SumHolds + Holds[i];
end;
{ split if user assigned all holds = 0 }
If (SumHolds = 0) then
Goto NoTrade;
If (SumHolds > TotHolds) then
for i := 1 to 3 do
If (Port1Buy[i] = 'S') then
Holds[i] := TotHolds div P1Buy;
SumHolds := 0;
for i := 1 to 3 do
If (Port2Buy[i] = 'S') then begin
if (Holds[i] < 0) then
Holds[i] := TotHolds div P2Buy;
SumHolds := SumHolds + Holds[i];
end;
If (SumHolds > TotHolds) then
for i := 1 to 3 do
If (Port2Buy[i] = 'S') then
Holds[i] := TotHolds div P2Buy;
NormalVideo;
SelectWindow(2);
RestoreScreen;
GoToXY(X,Y);
{ notify user Trading Macro is active }
TextColor(White);
TextBackground(Cyan);
SelectWindow(1);
ClrScr;
Write(' === ALT T- Tradewars Paired Port Trading. ALT Q Quits. === ');
NormalVideo;
SelectWindow(2);
GoToXY(X,Y);
{ trading loop }
REPEAT
{ Trade until a user types ALT-Q or routine hits exit condition}
TradeAtAPort(Port1Buy,P1_4Sale,P1B,P1S,P1F,Holds,P1Haggle,Loop);
If Loop then
MoveToANewPort(Port2,Loop);
If Loop then
TradeAtAPort(Port2Buy,P2_4Sale,P2B,P2S,P2F,Holds,P2Haggle,Loop);
If Loop then
MoveToANewPort(Port1,Loop);
UNTIL NOT Loop;
SaveScreen(X,Y);
TextColor(Yellow);
TextBackground(Blue);
GoToXY(10,10);WriteLn(' ');
GoToXY(10,11);WriteLn(' Exiting TRADE Macro ');
GoToXY(10,12);WriteLn(' ');
Delay(3000);
NormalVideo;
RestoreScreen;
GotoXY(X,Y);
END { if NTraded > 0 }
ELSE BEGIN
NoTrade:
{ no products to trade, so split }
SelectWindow(2);
RestoreScreen;
GoToXY(X,Y);
SaveScreen(X,Y);
TextColor(White);
TextBackground(Red);
GoToXY(10,10);WriteLn(' ');
GoToXY(10,11);WriteLn(' No products are traded between these two ports ');
GoToXY(10,12);WriteLn(' ');
Delay(3000);
NormalVideo;
RestoreScreen;
GoToXY(X,Y);
END;
END;
Procedure Steal;
Var
Port1Buy, Port2Buy : String;
P1b, P1s : real3;
P1F : Real3;
NTraded, MaxNBought : integer;
P1_4Sale,P2_4Sale : integer;
P1Haggle, P2Haggle : Integer;
P1Buy, P2Buy : integer;
TotHolds,SumHolds : integer;
Holds : Int3;
Loop : Boolean;
HasSold : Boolean;
X,Y,i : integer;
BEGIN
SaveScreen(X,Y);
Window(5,5,40,15);
YellowVideo;
ClrScr;
Loop := TRUE;
for i := 1 to 3 do begin
P1F[i] := DefaultFactor;
P1B[i] := DefaultBuy;
P1S[i] := DefaultSell;
end;
Write(' Port Type: ');
ReadLn(Port1Buy);
{ if somebody enters a port class, convert it to the 3 char string }
If ((length(Port1Buy) = 1) and (isdigit(Port1Buy[1]))) then
Port1Buy := ClassStr[Ord(Port1Buy[1]) - Ord('0')];
Port2Buy := Port1Buy;
Port2Buy[3] := 'S';
{ Finding out how many products we can "trade" }
Process_Port_Pair(Port1Buy,Port2Buy,NTraded,P1Buy,P2Buy,
P1Haggle,P2Haggle,P1_4Sale,P2_4Sale);
{ if we can sell equipment to this port, then steal }
If (NTraded > 0) THEN
BEGIN
Write(' How many Holds to Trade with : ');
ReadLn(TotHolds);
For i := 1 to 3 do begin
If i = 3 then
Holds[i] := TotHolds
else Holds[i] := 0;
end;
NormalVideo;
SelectWindow(2);
RestoreScreen;
GoToXY(X,Y);
{ notify user Stealing Macro is active }
TextColor(White);
TextBackground(Cyan);
SelectWindow(1);
ClrScr;
Write(' === ALT S- Tradewars Steal/Sell. ALT Q Quits. === ');
NormalVideo;
SelectWindow(2);
GoToXY(X,Y);
{ stealing loop }
HasSold := FALSE;
REPEAT
{ Trade until a user types ALT-Q or routine hits exit condition}
StealAtAPort(Loop,HasSold,Holds[3],STwo);
If Loop then begin
TradeAtAPort(Port1Buy,P1_4Sale,P1B,P1S,P1F,Holds,P1Haggle,Loop);
HasSold := TRUE;
end;
UNTIL NOT Loop;
SaveScreen(X,Y);
TextColor(Yellow);
TextBackground(Blue);
GoToXY(10,10);WriteLn(' ');
GoToXY(10,11);WriteLn(' Exiting STEAL Macro ');
GoToXY(10,12);WriteLn(' ');
Delay(3000);
NormalVideo;
RestoreScreen;
GotoXY(X,Y);
END { if NTraded > 0 }
ELSE BEGIN
{ no Equipment to sell, so split }
SelectWindow(2);
RestoreScreen;
GoToXY(X,Y);
SaveScreen(X,Y);
TextColor(White);
TextBackground(Red);
GoToXY(10,10);WriteLn(' ');
GoToXY(10,11);WriteLn(' Equipment is not bought at this port ');
GoToXY(10,12);WriteLn(' ');
Delay(3000);
NormalVideo;
RestoreScreen;
GoToXY(X,Y);
END;
END;
Procedure FivePointSteal;
Var
Port1Buy, Port2Buy : String;
P1b, P1s : real3;
P1F : Real3;
NTraded, MaxNBought : integer;
P1_4Sale,P2_4Sale : integer;
P1Haggle, P2Haggle : Integer;
P1Buy, P2Buy : integer;
TotHolds,SumHolds : integer;
Bp5p , Fo5p : integer;
Holds : Int3;
Loop : Boolean;
HasSold : Boolean;
X,Y,i : integer;
BEGIN
SaveScreen(X,Y);
Window(5,5,40,15);
YellowVideo;
ClrScr;
Loop := TRUE;
for i := 1 to 3 do begin
{ none of these are used but it keeps process_port_pair happy }
P1F[i] := DefaultFactor;
P1B[i] := DefaultBuy;
P1S[i] := DefaultSell;
end;
WriteLn(' 5 Pt Steal/Sell:');
Write(' Port Type: ');
ReadLn(Port1Buy);
{ if somebody enters a port class, convert it to the 3 char string }
If ((length(Port1Buy) = 1) and (isdigit(Port1Buy[1]))) then
Port1Buy := ClassStr[Ord(Port1Buy[1]) - Ord('0')];
Port2Buy := Port1Buy;
Port2Buy[3] := 'S';
{ Finding out how many products we can "trade" }
Process_Port_Pair(Port1Buy,Port2Buy,NTraded,P1Buy,P2Buy,
P1Haggle,P2Haggle,P1_4Sale,P2_4Sale);
{ if we can sell equipment to this port, then steal }
If (NTraded > 0) THEN
BEGIN
Write(' How many Holds to Trade with : ');
ReadLn(TotHolds);
For i := 1 to 3 do begin
If i = 3 then
Holds[i] := TotHolds
else Holds[i] := 0;
end;
NormalVideo;
SelectWindow(2);
RestoreScreen;
GoToXY(X,Y);
{ notify user Stealing Macro is active }
TextColor(White);
TextBackground(Cyan);
SelectWindow(1);
ClrScr;
Write(' === ALT 5- 5 Point Steal/Sell. ALT Q Quits. === ');
NormalVideo;
SelectWindow(2);
GoToXY(X,Y);
{ stealing loop }
BP5P := 0;
FO5P := 0;
HasSold := FALSE;
REPEAT
{ Trade until a user types ALT-Q or routine hits exit condition}
StealAtAPort(Loop,HasSold,Holds[3],SFive);
If Loop then begin
FivePointTrade(Port1Buy,P1_4Sale,BP5P,Fo5p,Holds,P1Haggle,Loop);
HasSold := TRUE;
end;
UNTIL NOT Loop;
SaveScreen(X,Y);
TextColor(Yellow);
TextBackground(Blue);
GoToXY(10,10);WriteLn(' ');
GoToXY(10,11);WriteLn(' Exiting STEAL Macro ');
GoToXY(10,12);WriteLn(' ');
Delay(3000);
NormalVideo;
RestoreScreen;
GotoXY(X,Y);
END { if NTraded > 0 }
ELSE BEGIN
{ no Equipment to sell, so split }
SelectWindow(2);
RestoreScreen;
GoToXY(X,Y);
SaveScreen(X,Y);
TextColor(White);
TextBackground(Red);
GoToXY(10,10);WriteLn(' ');
GoToXY(10,11);WriteLn(' Equipment is not bought at this port ');
GoToXY(10,12);WriteLn(' ');
Delay(3000);
NormalVideo;
RestoreScreen;
GoToXY(X,Y);
END;
END;
{
this is a new experimental multistealing algorithm;
the idea is to get a more efficient steal/sell cycle
for those individuals who can only steal a few holds
but have many holds on their ships, say, an individual
with 989 exp and a 250 hold colonial transport. By
stealing repeatedly until the ship is filled, you save
sell turns, and buy selling more at once, increase your
odds of getting a 5 point sale. Simply put, this
algorithm makes more money than a traditional 5 point
algorithm under certain conditions.
}
Procedure MultiSteal;
Const
Risk = 0.0333333333; { assuming 1/30 chance of getting caught }
Var
Port1Buy, Port2Buy, ExpStr : String;
P1b, P1s : real3;
P1F : Real3;
NTraded, MaxNBought : integer;
P1_4Sale,P2_4Sale : integer;
P1Haggle, P2Haggle : Integer;
P1Buy, P2Buy : integer;
TotHolds,SumHolds : integer;
Bp5p , Fo5p : integer;
Holds : Int3;
Loop : Boolean;
HasSold : Boolean;
X,Y,i : integer;
experience, MostEff, EffHolds,ec1 : integer;
eff,neweff,rtemp : real;
OneMinusRisk, lnOMR, NRisk : real;
holdspt, newholds, maxcyc, nturns, turns, xsteal : integer;
StealHolds : integer;
BEGIN
OneMinusRisk := 1.0 - Risk;
lnOMR := ln(OneMinusRisk);
SaveScreen(X,Y);
Window(5,5,40,15);
YellowVideo;
ClrScr;
Loop := TRUE;
for i := 1 to 3 do begin
{ none of these are used but it keeps process_port_pair happy }
P1F[i] := DefaultFactor;
P1B[i] := DefaultBuy;
P1S[i] := DefaultSell;
end;
WriteLn(' Multi Steal/Sell: ');
Write(' Port Type: ');
ReadLn(Port1Buy);
{ if somebody enters a port class, convert it to the 3 char string }
If ((length(Port1Buy) = 1) and (isdigit(Port1Buy[1]))) then
Port1Buy := ClassStr[Ord(Port1Buy[1]) - Ord('0')];
Port2Buy := Port1Buy;
Port2Buy[3] := 'S';
{ Finding out how many products we can "trade" }
Process_Port_Pair(Port1Buy,Port2Buy,NTraded,P1Buy,P2Buy,
P1Haggle,P2Haggle,P1_4Sale,P2_4Sale);
{ if we can sell equipment to this port, then steal }
If (NTraded > 0) THEN
BEGIN
Write(' Your Experience : ');
BuildString(ExpStr);WriteLn;
Write(' How many Holds to Trade with : ');
ReadLn(TotHolds);
experience := 0;
If (Length(ExpStr) > 0) then begin
Val(ExpStr,experience,ec1);
if (ec1 <> 0) then
experience := 0;
end;
if (experience > 0) then begin
rtemp := experience / 100;
holdspt := round(5*rtemp); { round to nearest 5 holds of exp/20 }
if (holdspt >= totholds) then begin
stealholds := totholds;
mosteff := 1;
{
trading efficiency = (holds sold per turn - risk*#holds that can
be lost per turn - risk*loss of holds that could be stolen with
lost experience per turn)
}
eff := (stealholds - Risk*(stealholds + experience/200))
/(mosteff + 1.0);
end
else begin
maxcyc := totholds div holdspt + 1;
mosteff := 0;
eff := 0.0;
stealholds := 0;
for turns := 1 to maxcyc do begin
NRisk := 1.0 - exp(turns*lnOMR);
nturns := turns + 1;
if (turns*holdspt > TotHolds) then
newholds := TotHolds div turns
else newholds := holdspt;
{ ok, how efficient is this potential loop? }
{
efficiency = turns*holds/# turns for loop -
cumulative risk for loop turns * (
mean number of holds to be lost +
holds equivalent to 10% of exp)/
# turns for loop
}
neweff := (turns*newholds - NRisk*
(newholds*(turns+1)/2 + experience/200))/nturns;
if (neweff > eff) then begin
mosteff := turns;
eff := neweff;
stealholds := newholds;
end;
end; { for turns }
end;
end
else begin
StealHolds := TotHolds;
MostEff := 1;
eff := stealholds*(1 - Risk)/(mosteff + 1.0);
end;
For i := 1 to 3 do begin
If i = 3 then
Holds[i] := StealHolds*MostEff
else Holds[i] := 0;
end;
Writeln(' Stealing ',StealHolds:3,' Holds for ');
WriteLn(' ',MostEff:1,' Consecutive Turns.');
WriteLn(' Eff = ',Eff:7:2,' holds/turn.');
Delay(2500);
NormalVideo;
SelectWindow(2);
RestoreScreen;
GoToXY(X,Y);
{ notify user Stealing Macro is active }
TextColor(White);
TextBackground(Cyan);
SelectWindow(1);
ClrScr;
Write(' === ALT 6 - MultiSteal Steal/Sell. ALT Q Quits. === ');
NormalVideo;
SelectWindow(2);
GoToXY(X,Y);
{ stealing loop }
BP5P := 0;
FO5P := 0;
HasSold := FALSE;
REPEAT
{ Trade until a user types ALT-Q or routine hits exit condition}
xsteal := 0;
While ((xsteal < Mosteff) and Loop) do begin
StealAtAPort(Loop,HasSold,StealHolds,SMulti);
Inc(xsteal);
end;
If Loop then begin
FivePointTrade(Port1Buy,P1_4Sale,BP5P,Fo5p,Holds,P1Haggle,Loop);
HasSold := TRUE;
end;
UNTIL NOT Loop;
SaveScreen(X,Y);
TextColor(Yellow);
TextBackground(Blue);
GoToXY(10,10);WriteLn(' ');
GoToXY(10,11);WriteLn(' Exiting STEAL Macro ');
GoToXY(10,12);WriteLn(' ');
Delay(3000);
NormalVideo;
RestoreScreen;
GotoXY(X,Y);
END { if NTraded > 0 }
ELSE BEGIN
{ no Equipment to sell, so split }
SelectWindow(2);
RestoreScreen;
GoToXY(X,Y);
SaveScreen(X,Y);
TextColor(White);
TextBackground(Red);
GoToXY(10,10);WriteLn(' ');
GoToXY(10,11);WriteLn(' Equipment is not bought at this port ');
GoToXY(10,12);WriteLn(' ');
Delay(3000);
NormalVideo;
RestoreScreen;
GoToXY(X,Y);
END;
END;
BEGIN
{ initialize buy and sell margins and trading factor }
DefaultBuy := 0.96;
DefaultSell := 1.04;
DefaultFactor := 2.3333333; { equal to f = 0.3 in 2nd order theory }
DeltaFactorOffer := 25;
DeltaFactorPsp := 4;
END.